import java.util.*;

abstract public class board{
	
	protected int id = -1;
	protected String title;	// a board's name = title
	
	//	userList is used to record the name of the board's user
	protected ArrayList<Integer> userIdList = new ArrayList<Integer>();
	
	//	adminList is used to record weather a user is a administrator or not
	protected ArrayList<Boolean> adminList = new ArrayList<Boolean>(); 
	
	// 	a board can have many lists on it, Lists is used to keep the lists
	protected aListInfor Lists = null; 
	
	// a board can have many labels on it
	private labelInfor Labels = null; 
	
	// a board can have many members on it
	private memberInfor Members = null; 
	
	protected boolean enabled = true;	// set the board is able to use or not
	
	protected int ownerId;	//  record owner ID
	
	protected boolean messageEnabled;	//  set the board can be left message or not

	protected String comment = null;
	
	//to  get the Board's name/title 
	String getTitle(){
		return title;
	}

	//to add a new member to the board
	void addUserId(int userId){
		this.userIdList.add(userId);
		this.adminList.add(false);
	}
	
	/*
	 *  setTitle(String name) :
	 *  	to set the board's name/title
	 *  	name : the board's name/title
	 */
	void setTitle(String name){
		this.title = name;
	}
	
	int getId(){
		return this.id;
	}
	String getComment(){
		return this.comment;
	}
	
	// set comment
	abstract void setComment(String cmt,int ownerId);
	 
	//createNewBoard() : create a new board, which will be defined at boardInfor
	abstract void createNewBoard(int ownerId,int id);
	
	/*
	 *  edit(String newName,boolean isOwner) :
	 *  	use to edit the board's information
	 *  	newTitle: new name we use to reset the board's name
	 *  	enabled	: enabled a board or not 
	 *  	userId 	: user who want to edit the board
	 */
	abstract void edit(String newTitle,boolean enabled,int userID);
	
	/*
	 * 	invite(String user) :
	 * 		to invite a user to the board
	 * 		user	: the user who has been invited
	 */
	abstract void invite(int userId);
	
	/*
	 *  close(String user) :
	 *  	to close the board, and will not be seen until reopening
	 *  	userId	: the user's Id who close the board
	 */
	abstract void close(int userId);
	
	/*
	 *  toRemove(int userId) :
	 *  	to remove the board forever
	 *  	userId	: the use who remove the board
	 */
	abstract void toRemove(int userId);
	
	/*
	 * 	reopen(int userId) : 
	 * 		to reopen a board which had been closed
	 * 		userId	: the use who reopen the board
	 */
	abstract void reopen(int userId);
	
	/*
	 *  preference(boolean vote,boolean leftMessage) :
	 * 		set the board can use be voted and left message or not
	 */
	abstract void preference(boolean leftMessage,int userId);
	
	/*
	 *  setAdmin(int setterId,int userId,boolean isAdmin) :
	 *  	a setter who is an administrator set use
	 *  	setterId	: someone who set other as a administrator
	 *  	userId	: someone who will be set as a administrator
	 *  	isAdmin : set as an administrator or not
	 */
	abstract void setAdmin(int setterId,int userId,boolean isAdmin);

	
	/*
	 * 	attachLists(aListInfor aListList) :
	 * 		attach a sequence of lists to the board
	 * 		aListList 	: the target
	 */
	abstract void attachLists(aListInfor aListList);
	
	/*
	 * 	attachLabels(labelInfor labelList) :
	 * 		attach a sequence of labels to the board
	 * 		labelList 	: the target
	 */	
	abstract void attachLabels(labelInfor labelList);           //renew
	

	/*
	 * 	attachUsers(labelInfor labelList) :
	 * 		attach a sequence of labels to the board
	 * 		labelList 	: the target
	 */	
	abstract void attachMembers(memberInfor memberList);           //renew
	
	
	
	/*
	 *  checkAuthority(String user) :
	 *  	check user is an administrator or not
	 *  	user	: check target 
	 */
	protected boolean checkAuthority(int userId){
		for (int i = 0; i < userIdList.size(); i++){
			if (userIdList.get(i) == userId){
				if (adminList.get(i) == true)
					return true;
			}
		}
		return false;
	}
	
	
	
	/*
	 *  getBumOfListOnTheBoard() :
	 *  	return the number of list on the board
	 */
	protected int getBumOfListOnTheBoard(){
		if (Lists != null)
			return Lists.getListSize();
		else return 0;
	}
	
	/*
	 *  getBumOfLabelOnTheBoard() :
	 *  	return the number of label on the board
	 */	
	protected int getBumOfLabelOnTheBoard(){                     //renew
		if (Labels != null)
			return Labels.getLabelSize();
		else return 0;
	}

	
	
	/*
	 *  getBumOfUserOnTheBoard() :
	 *  	return the number of user on the board
	 */	
	protected int getNumOfMemberOnTheBoard(){     
		if (Members != null)//renew
			return Members.getNumOfMember();
		else return 0;
	}

	
	
	/*
	 *  setLists(aListInfor list) :
	 *  	do the action of attachment
	 */
	protected void setLists(aListInfor list){
		this.Lists = list;
	}
	
	protected aList getListOnBard(int listId){
		return Lists.getList(listId);
	}

	protected ArrayList<aList> getAllList(){
		return this.Lists.getAll();
	}
	protected ArrayList<member> getAllMember(){
		return this.Members.getAll();
	}
	protected ArrayList<label> getAllLabel(){
		return this.Labels.getAll();
	}
	
	
	/*
	 *  setLabels(LabelInfor label) :
	 *  	do the action of attachment
	 */
	protected void setLabels(labelInfor label){                  //renew
		this.Labels = label;
	}
	
	
	/*
	 *  setUsers(userInfor user) :
	 *  	do the action of attachment
	 */
	protected void setMembers(memberInfor member){                  //renew
		this.Members = member;
	}
	
	protected member getMemberOnBoard(int memberId){
		return this.Members.getMember(memberId);
	}
	
}

/*
 * function used by board
 */
abstract class boardEditor{
	private ArrayList<board> boardList = new ArrayList<board>();

	/*
	 *  do close the board
	 */
	
	private board findBoard(int targetId){
		for(board doc : boardList) {
            if (targetId == doc.getId()){
            	return doc;
            }
        }
		board doc = null;
		return doc;
	}
	
	void createNewBoard(String boardTitle,int createById, int boardId) {
        board doc = createBoard();
        doc.setTitle(boardTitle);
        doc.createNewBoard(createById,boardId);
        boardList.add(doc);
    }
    
    /*
     * add list:"aLists" to board:"boardTitle"
     */
    void attachLists(aListInfor aLists, int targetId){
    	for(board doc : boardList) {
            if (doc.getId() == targetId){
            	doc.attachLists(aLists);
            }
        }
    }
    void attachLabels(labelInfor labels, int boardId){          //renew
    	board doc = findBoard(boardId);
    	doc.attachLabels(labels);
    }
    void attachMembers(memberInfor members, int boardId){          //renew
    	board doc = findBoard(boardId);
    	doc.attachMembers(members);
    }
    
    
    /*
     * get how many list on the board
     */
    int getNumOfListOnTheBoard(int targetId){
		for(board doc : boardList) {
			if (doc.getId() == targetId){
            	return doc.getBumOfListOnTheBoard();
            }
        }
		return 0;
	}
 
    /*
     * get how many label on the boaed
     */
    int getNumOfLabelOnTheBoard(String aBoardTitle){                  //renew
		for(board doc : boardList) {
			if (doc.getTitle() == aBoardTitle){
            	return doc.getBumOfLabelOnTheBoard();
            }
        }
		return 0;
	}
    

    /*
     * get how many user on the boaed
     */
    int getNumOfMemberOnTheBoard(int BId){                  //renew
		board doc = findBoard(BId);
        return doc.getNumOfMemberOnTheBoard();
	}
    
    int getBoardSize() {                                             //renew
    	return boardList.size();
    }
    
    /*
     * the following is a sequence of "edit" function
     * which is separated as many small functions 
     */
    void editTitle(int targetId,String newTitle,int editById){
    	board doc = findBoard(targetId);
    	doc.edit(newTitle, doc.enabled, editById);
    }
    void editLeftMessage(int targetId,boolean leftMessage,int editById){
    	board doc = findBoard(targetId);
    	doc.preference(leftMessage, editById);
    }
    void editAdmin(int targetId,int userId,boolean isAdmin,int editById){
    	board doc = findBoard(targetId);
    	doc.setAdmin(editById, userId, isAdmin);
    }
    void editInvite(int targetId,int userId,int editById){
    	board doc = findBoard(targetId);
    	doc.invite(userId);
    }
    void editReopen(int targetId,int editById){
    	board doc = findBoard(targetId);
    	if ( doc.enabled == false ){
    		doc.edit(doc.getTitle(), true, editById);
    	}
    }
    void editClose(int targetId,int editById){
    	board doc = findBoard(targetId);
    	if ( doc.enabled == true ){
    		doc.edit(doc.getTitle(), false, editById);
    	}
    }
    void editRemove(int targetId,int editById){
    	board doc = findBoard(targetId);
    	doc.toRemove(editById);
    }
    void editComment(int targetId,String comment,int editById){
    	board doc = findBoard(targetId);
    	doc.setComment(comment,editById);
    }
    board getBoard(int targetId){
        return findBoard(targetId);
 
    }
    aList getListOnBoard(int targetId,int listId){
    	board doc = findBoard(targetId);
    	return doc.getListOnBard(listId);
    }
    member getMemberOnBoard(int targetId,int memberId){
    	board doc = findBoard(targetId);
    	return doc.getMemberOnBoard(memberId);
    }
    ArrayList<board> getALL(){
    	return boardList;
    }

    
	abstract board createBoard(); // factory method
}
class boardInfor extends boardEditor{
	board createBoard() {	// below method definition is as previewer method description
        return new board() {
        	void createNewBoard(int ownerId,int boardId){
        		//System.out.println("createNewBoard " + this.getTitle());
        		this.ownerId = ownerId;
        		this.id = boardId;
        		this.enabled = true;
        	}
        	
        	/*
        	 * functions prepare to do 
        	 * 
        	 */
        	void edit(String newTitle,boolean enabled,int userID){
        		//System.out.println("edit");
        		if (userID == this.ownerId){
        			this.setTitle(newTitle);
        			this.enabled = enabled;
        		}
        		else {
        			System.out.print("You have no authority to edit the board : " + this.getTitle());
        		}
        		
        	}
        	void invite(int userId){
        		//System.out.println("invite");
        		this.addUserId(userId);
        		/*
        		 *  here also have to send a mail to notify userId,
        		 *  use the function like "void notified(int fromId,int dstId)"
        		 */
        		
        	}
        	void close(int userId){
        		this.edit(this.getTitle(), false, userId);
        		//System.out.println("closeBoard by" + userId);
        	}
        	void toRemove(int userId){
        		if ( userId == this.ownerId){
        			/*
        			 * here have to DELETE : 
        			 * 		1. the board associated with it id
        			 * 		2. all Lists on the board
        			 * form DATABASE
        			 */
        		}
        		//System.out.println("remove by" + userId);
        	}
        	void reopen(int userId){
        		this.edit(this.getTitle(), true, userId);
        		//System.out.println("reopen");
        	}
        	void preference(boolean leftMessage,int userId){
        		if ( this.checkAuthority(userId) ){
        			this.messageEnabled = leftMessage;
        		}
        		//System.out.println("preference");
        	}
        	void setAdmin(int setterId,int userId,boolean isAdmin){
        		if ( this.checkAuthority(setterId) ){
        			for (int i = 0; i < this.userIdList.size(); i++){
        				if ( userId == this.userIdList.get(i) ){
        					this.adminList.set(i, isAdmin);
        				}
        			}
        		}
        		//System.out.println("setAdmin");
        	}
        	void attachLists(aListInfor aListList){
        		
        		this.setLists(aListList);
        	}
        	
        	void setComment(String cmt,int ownerId){
        		if ( ownerId == this.ownerId)
        			this.comment = cmt;
        		else 
        			System.out.println("You have no authority to edit comment");
        	}
        	
        	void attachLabels(labelInfor labelList){                 //renew
        		
        		this.setLabels(labelList);
        	}
        	void attachMembers(memberInfor memberList){                 //renew
        		this.setMembers(memberList);
        	}
        };
    }
}

/*
 * database	:	
 * 		board	:
 * 			leftMessage // no need
 * 
 * see		:
 * 		toRemove in	"boardInfor"
 * 		invite	in 	"boardInfor"
 * 
 * also		:
 * 		we need a class which is use to manage a list of users, named "users"
 * 
 */

